package com.iwunu.gateway.util;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

import lombok.Synchronized;

/**
 * @ Version: 1.0
 * @ Time: 2022/10/25 16:53
 * @ Description:
 */
@Component
public class FeatureSoUtil {
	private static Logger logger = LoggerFactory.getLogger(FeatureSoUtil.class);
    /**
     * so库映射的接口
     */
    private interface NativeCpp extends Library {

        /**
         * 映射的方法
         *
         * @param param
         * @return
         */
		long Fm226FaceCropper(String filename, Pointer fea_size, Pointer err_code, byte[] res);
    }

    /**
     * 加载so库
     */
    private static class SoLibImpl implements NativeCpp {
        static NativeCpp INSTANCE;
        static {
            try {
                // 也可以采用其他方法加载so库文件,或将so文件放在项目中
                INSTANCE = (NativeCpp) Native.synchronizedLibrary(Native.load("/opt/so/Fm226FeatureDll.so", NativeCpp.class));
                
                System.out.println("Load SoLib success");
            } catch (Exception e) {
                // 异常处理
                INSTANCE = null;
                System.out.println("/Fm226FeatureDll.so!");
            }
        }
        @Override
        public native long Fm226FaceCropper(String filename, Pointer fea_size, Pointer err_code, byte[] res);
    }

    /**
     * 对外暴露的工具方法,在此方法中调用so库中的native方法
     *
     * @param param
     * @return
     */
    @Synchronized
    public static JSONObject invoke(String filename) {
        if (null != SoLibImpl.INSTANCE) {
        	byte res[] = new byte[9999];
        	JSONObject resultData = new JSONObject();
    		Pointer size = new Memory( Native.getNativeSize(Integer.class) );
    		Pointer code = new Memory( Native.getNativeSize(Integer.class) );
    		SoLibImpl.INSTANCE.Fm226FaceCropper(filename, size, code,res);
    		logger.error("invoke fea_size: " + size.getInt(0));
    		logger.error("invoke err_code: " + code.getInt(0));
    		int arrSize = size.getInt(0);
    		String data = StringUtil.byte2hex(res, arrSize);
    		if(code.getInt(0)==0) {
    		 String crc = imageCRC(data);
    		 String imageData = data+crc;
    		 resultData.put("size", size);
    		 resultData.put("code", code.getInt(0));
    		 resultData.put("data", imageData);
     		 return resultData;
    		}

    		
        } else {
            throw new RuntimeException("无法执行native方法,请检查so库文件是否存在!");
        }
		return null;
    }
    
    
    private static String imageCRC (String hexString) {
    	  // 多项式
        long polynomial = 0xEDB88320L;
        // 初始值
        long initialValue = 0xFFFFFFFFL;
        // 结果异或值
        //long xorValue = 0;
        long crc = calculateCRC(hexString, polynomial, initialValue);
        return Long.toHexString(crc).toUpperCase();
    }

    public static long calculateCRC(String hexString, long polynomial, long initialValue) {
        byte[] data = hexStringToByteArray(hexString);
        long crc = initialValue;
        long xx;
        for (byte b : data) {
			xx = (((byte)crc&0xff)^(b&0xFF))&0xff;
            for (int i = 8; i>0; i--) {
                if ((xx & 0x1L) != 0) {
                    xx = (xx >> 1) ^ polynomial;
                } else {
                    xx >>= 1;
                }
            }
            crc = xx ^ (crc >> 8);			
            crc &= 0xFFFFFFFFL;
        }
        return crc;
    }
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
    public static void main(String[] args) {
		String hexData ="347B8DB9129DAD3C62FB9EBD40CF053CF6791DBC9C73AB3DC494743DAF89423D583B3B3CA0CC1EBD7812C2BC596D7FBDED4D493A2BAC7E3C7C4DEBBCC1EF063D485BADBDFCA08EBD5AC00A3DC25CD63C618F4B3D764D8ABDB7305E3CC3BD9ABCC3E0E53A795CD93D93591ABDC7B18ABD93C1E63C54FEAF3C0BBD313BD2F6333A186F58BB33B92BBD76C0E4BB956B05BD2B7B573D608B9D3D762158BD81AE47BD4B68B43DDD2D2ABD2BDF603BE22763BDFE6F923BDF0CC0BB8F8838BC0F833BBDE3504F3C3BA573BD98521E3DF46FE8BB915A253CAA9C203DF79A613D0B5AFD3C2C6F313CA2B12EBC133C843B6BBAB53C7F56343AE4343ABD253D8F3DE4A7613CA6F822BD48548C3C6A8320BCC9CA23BC0BBC1BBDD3F68BBDCC8EAFBC3D7833BD4CA8DABCD07417BDF77262BD4D8A1C3DDC0135B93E5D033D67553DBD2E7ED13CA55DEF3B5D6E923C846C493D706418BCA55D22BDDC57553DE1442F3D7582CFBCF3694EBD30F897BCB05A04BDF834523CC1E409BD25D1083D7B61503D3F80583D21B60BBD463DB33C85C62C3D12479CBCB6ECB4BCB265F8BC421D6DBDE44C0D3DAB8B773DC07856BDBBB6A2BD9DCEB1BC0D806BBD31A7D4B9E6C12D3CE5252B3D9FBE1B3D4B3D6FBD1172113E41C9283DF003C63C78AAB33D75C027BD125FFF394F05373D6A1DD73B8651573C76D6F8BCB6E98BBDAF0ED7BC164557BB3D49D8BAAF7C95BD8A2233BB381F64BCFEC0B23C9D8B20BDD5E5AF3C9BAF4A3DF2A55CBD51D3DC3C8D4ACF3B2B414ABD5DAD8D3DBC3B303C7E9FE4BBA0ED5DBDAE50E4BC152952BD94A653BD09FD56BD22C88BBDEEA120BC94D1AC3C3E9030BD5B8983BCDFE8D8BB5316BC3CD656D13C4D800CBD0A42C9BDBD6D5EBD4BF4563D9AA2C9BBFC7B013D38E096BDA6B5933D20F52ABC300F8A3CBFAD513D84896EBCAC29E53C956CE4BB795E6FBC63A6A43C2EB8423C112E0E3D294F50BDA90CA83C7E1ABFBCA1A76BBC1AC8A1BDF565873CA933BCBCF657B53DD11AFEBD47EBFB3C932DD0BC9948EA3C8EF3E0BB124A8BBD454B0F3D8445B33DF6F98D3C016DA53C28A905BCAD2BC9BC19103F3CDD78F0BAFD83B73C9937303DE25D2FBDBC409C3CF0BE743D0CDD413CE6E7CEBAA706ADBB995D883D21E13ABC5956473CBF8466BD3D589BBC24FEA8BAA324D63D372A3CBD736944BD12562A3B4B8A08BD5E289C3BE06CF2BCE4D550BDFDC53CBC397BBEBC924E59BD082D14BDFE05A6BB2C313E3DD5741F3D8A1681BCA4D069BD35788F3C43B5293D744A5ABA0C8560BC1125ADBB76C195BDA48D093D82A492BDBC7A8FBB970F39BD3E7A19BD890CC63954AFF8BC82233B3C1BEE443C0E4440BD6FF7F5BC2A8B17BDFD0F523D9B815E3DEEB40A3D934051BB1AE0503C819751BD2C3DEABCF91BC7BC95272FBD1D1839BDD77C4EBBCFA4CEBCF221903D491E513DA642E13D6449713D6D4F8DBD1B324ABD119B4A3C61FE03BD30887CBDA3CAFABCEBB9D93B6ED4C63C41B6853B37D804BDA31F31BD267C8DBD0FA5B3BDAA4C063D4DD918BD3FCA5CBD6D1B6A3D07214C3D0766263D3434E93BCA40B0BC7805C9BB956276BDD934A03CFC533E3C9C37CB3D8501753D8180F5BD9913C03DE72AE2BCD523AE3D4E870CBCDD2EAB3CE02D1C3DDB36A0BD12B8063C72DB823D578E32BC4A8412BC8E08303D63E69E3D1581393D74651A3C7CAC303B3B7A0A3DDE9AD03DCF402DBD33F52D3D6477343C07255ABB96762DBD06DBCEBC2A59A0BBC19631BD58ED12B9890CA2BC9FF9ED3B10942EBD5B1D17BD0F64A1BD3116AF3B15FFC23C206D303D9A45483D66AB5BBD5C3F643C8629343D1657F7BCAF85BC3CAF5FDC3BCB23173D97D927BDA9E449BD865F933C515312BCA23612BE909E96BD02296FBDCFA9FC3D89058ABC486864BB88FEE0BC524A8ABDF293003DE9F3EF3BF395683D0AC912BDB878C0BD53A8C03AA27D60BB33B2F0BCC73015BDF39E9D3D3A8ED7BC66E80B3CCDFF153C8E2F96BD6A8AA03D15CA0A3D208F843D3D451DBDF23F423DF9F05FBDE814543D5DE0D73B9FF8233D6435A23D44CAD13C9233C43CA45B7F3D97EF5FBDFCECCE3C71F45CBC969F653D4D1EB4BC3FE02E3D5C058DBDD518783DE26B283D7871083D33318BBCF4118CBC1FA0B23C7613743D3E1331BCFE9D1D3DB43DDF3C82308ABBA15208BD11D666BDC3225F3DB04E9DBD3A1F993D7FF88FBCE952B0BD62DB023DE86026BD1C01223DC5CEEBBC8BE7433D5EBD17BD483A17BD19E1A13D234F4B3D3A190BBCB498843C3E70543D8D05B5BDBFBC3D39908DAF3D7847683CB70B123B643C69BC593CA73D1391C4BCB2DB053D1504353C62DF80BDE714AEBAE88A953DD025F3BB9F7FAEBC8E9F9EBC672173BC8DFF9BBB77CF29BD04CBE1BC7EAE403C84D5263D3960853D47B642BDC40EB93DCEA5763C882B583C5A7790BCE3BB7D3C3083513C1C2C863D3FA39D3D56B0513CCF305ABC478B20BBD4EEA93CE900A9BBE3579FBBDC19843D8842723DB514383B8381B8BCF42F80BC1AA3913DD0427DBD1E29FF3C3746903DBB33203C5A28AEBC6D7092BD75A8A0BD8983BE3D410122BC76F362BC7898A6BBD78413BD6F0A8E3D4221D13C9BE6E73BA057F4BCBA677D3D5A7988BBB23165BC6BB9113C2194423C32D234BC923BDC3C627644BD98756C3D4A05133C27340CBD1F4722BDBEB2C4BC3ED7813D851B07BCA6B4623DC03A44BDD091883DFBBCADBC57DE87BCCE442ABDEC015DBD3390A5BC1DF735BCF4F1053CFB0FBA3C15ADA33D8C8AED3C229970BD6F2D023D44548DBBB5EB65BB8177FE3CDCCFA13DDD80483B3D9C54BB28AA483D0FAC933C99CA56BDB3F8803C4CC8873B04FB0ABDF71C51BC385221BDBA13EC3CAFD14F1A";
	System.out.println("size:"+ imageCRC(hexData));
    }
}

